<?php
/**
 * appRain CMF
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/mit-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@apprain.com so we can send you a copy immediately.
 *
 * @copyright  Copyright (c) 2010 appRain, Team. (http://www.apprain.com)
 * @license    http://www.opensource.org/licenses/mit-license.php MIT license
 *
 * HELP
 *
 * Official Website
 * http://www.apprain.com/
 *
 * Download Link
 * http://www.apprain.com/download
 *
 * Documents Link
 * http ://www.apprain.com/docs
 */
 
class Component_PaypalExpress_Pgateway_PaypalExpress extends Component_Appstore_Helpers_Pgateway_Common
{
	const PAYMENT_SUCCESS_URL = '/payment-success';
	const STATUS_NAME = 'PaypalExpress';
	const PAYMENT_ACTION = "Sale";
	
	const API_SANDBOX_ENDPOINT ='https://api-3t.sandbox.paypal.com/nvp';
	const API_ENDPOINT ='https://api-3t.paypal.com/nvp';
	
	const PAYPAL_SANDBOX_URL = 'https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=';
	const PAYPAL_URL = 'https://www.paypal.com/cgi-bin/webscr&cmd=_express-checkout&token=';

	const SET_EXPRESS = 'SetExpressCheckout';
	const VERSION = 65.1;
	
	public function place()
	{
       $this->AssignPost()->Execute();
	}

	public function getStatusName()
	{
		return self::STATUS_NAME;
	}

	private function AssignPost()
	{
		$this->setXPaymentAction(self::PAYMENT_ACTION);

		$this->setXMethod(self::SET_EXPRESS)
			 ->setXVersion(self::VERSION)
			 ->setXPwd(App::Helper('Config')->siteInfo('paypalpro_password',false))
			 ->setXUser(App::Helper('Config')->siteInfo('paypalpro_username',false))
			 ->setXSignature(App::Helper('Config')->siteInfo('paypalpro_signature',false));

		$customer  = $this->getBillingAddress();
		$this->setXFirstName((isset($customer['fname'])?$customer['fname']:""))
			 ->setXLastName((isset($customer['lname'])?$customer['lname']:""))
			 ->setXAddress1((isset($customer['address_line_1'])?$customer['address_line_1']:""))
			 ->setXAddress2((isset($customer['address_line_2'])?$customer['address_line_2']:""))
			 ->setXCity((isset($customer['city'])?$customer['city']:""))
			 ->setXState((isset($customer['state'])?$customer['state']:""))
			 ->setXCountry((isset($customer['country'])?$customer['country']:""))
			 ->setXZip((isset($customer['zipcode'])?$customer['zipcode']:""))
			 ->setXEmail((isset($customer['email'])?$customer['email']:""))
			 ->setXPhoneno((isset($customer['phoneno'])?$customer['phoneno']:"")) ;
			 
		$customer  = $this->getShippingAddress();
		$this->setXShippingFirstName((isset($customer['fname'])?$customer['fname']:""))
			 ->setXShippingLastName((isset($customer['lname'])?$customer['lname']:""))
			 ->setXShippingAddress1((isset($customer['address_line_1'])?$customer['address_line_1']:""))
			 ->setXShippingAddress2((isset($customer['address_line_2'])?$customer['address_line_2']:""))
			 ->setXShippingCity((isset($customer['city'])?$customer['city']:""))
			 ->setXShippingState((isset($customer['state'])?$customer['state']:""))
			 ->setXShippingCountry((isset($customer['country'])?$customer['country']:""))
			 ->setXShippingZip((isset($customer['zipcode'])?$customer['zipcode']:""))
			 ->setXShippingEmail((isset($customer['email'])?$customer['email']:""))
			 ->setXShippingPhoneno((isset($customer['phoneno'])?$customer['phoneno']:"")) ;
	
		if($this->getAmount()>0){
			$this->setXAmount($this->getAmount());
		}
		else{
			throw new AppException($this->__('Invalid amount changed'));
		}
		$this->setXCurrencyCode('USD');
		return $this;
	}

	public function Execute()
	{
		$ord = App::Model('Order')->findById($this->getOrderid());

		$post_values = array(
			"METHOD"		=> self::SET_EXPRESS,
			"VERSION"		=> $this->getXVersion(),
			"PWD"			=> $this->getXPwd(),
			"USER"			=> $this->getXUser(),
			"SIGNATURE"		=> $this->getXSignature(),
			"returnURL" 	=> App::Config()->baseUrl("/paypalexpress/return"),
		    "cancelURL" 	=> App::Config()->baseUrl("/appstore"),
			
			"PAYMENTACTION"	=> $this->getXPaymentAction(),
			"CUSTOM" 	    => $this->getOrderid(),
			"AMT"			=> ($this->getXAmount()),

			"FIRSTNAME"		=> $this->getXFirstName(),
			"LASTNAME"		=> $this->getXLastName(),
			"STREET"		=> $this->getXAddress1(),
			"CITY"			=> $this->getXCity(),
			"STATE"			=> $this->getXState(),
			"ZIP"			=> $this->getXZip(),
			"COUNTRYCODE"	=> $this->getXCountry(),
			"CURRENCYCODE"	=> $this->getXCurrencyCode(),
			
			"SHIPTONAME"	=> $this->getXShippingFirstName() . ' ' . $this->getXShippingLastName(),
			"SHIPTOSTREET"  =>  $this->getXShippingAddress1(),
			"SHIPTOCITY"  	=>  $this->getXShippingCity(),
			"SHIPTOSTATE"  	=>  $this->getXShippingState(),
			"SHIPTOCOUNTRYCODE"  	=>  $this->getXShippingCountry(),
			"SHIPTOZIP"  	=>  $this->getXShippingZip(),
		
		);

		$Item = App::Model('Item')->findAllByOrderId($this->getOrderid());
		foreach($Item['data'] as $key=>$row){
			$post_values["L_NAME{$key}"] = $row['title'];
			$post_values["L_AMT{$key}"] = $row['unitprice'] + ($row['shippingcost']/$row['qty']);
			$post_values["L_QTY{$key}"] = $row['qty'];
		}

		if($ord['discount']	> 0 ){
			$post_values["L_NAME" . ($key+1)] = 'Discount';
			$post_values["L_AMT" . ($key+1) ] = $ord['discount'] * -1;
			$post_values["L_QTY" . ($key+1)] = '1';
		}

		$post_string = "";
		foreach( $post_values as $key => $value ){ $post_string .= "$key=" . urlencode( $value ) . "&"; }
		$post_string = rtrim( $post_string, "& " );

		$post_response = $this->callService($post_string);

		$response = $this->deformatNVP($post_response);

		$ack = strtoupper($response["ACK"]);
		if($ack=="SUCCESS")
		{
			$token = urldecode($response["TOKEN"]);
			
			$PAYPAL_URL = (App::Config()->Setting('paypalexpress_mode') == 'Sandbox') ? self::PAYPAL_SANDBOX_URL : self::PAYPAL_URL;
			
			echo App::Module("Cryptography")
				->jsonEncode(
				Array(
					"_status" =>"Redirect",
					"_location"=> $PAYPAL_URL.$token
				)
			);
			exit;
		}
		else{
			throw new AppException($this->__($response['L_LONGMESSAGE0']));
		}
	}
	
	public function callService($post_string=''){
	
		$API_ENDPOINT = (App::Config()->Setting('paypalexpress_mode') == 'Sandbox') ? self::API_SANDBOX_ENDPOINT : self::API_ENDPOINT;
		$request = curl_init($API_ENDPOINT);
		curl_setopt($request, CURLOPT_HEADER, 0); 
		curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($request, CURLOPT_POSTFIELDS, $post_string);
		curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE);
		$post_response = curl_exec($request);
		curl_close ($request);
		
		return $post_response;
	}
	
	public function OrderReviewStatus($token){
		
		$post_values = array(
			"METHOD"		=> 'GetExpressCheckoutDetails',
			"VERSION"		=> self::VERSION,
			"PWD"	=> App::Helper('Config')->siteInfo('paypalpro_password',false),
			"USER"	=> App::Helper('Config')->siteInfo('paypalpro_username',false),
			"SIGNATURE"	=> App::Helper('Config')->siteInfo('paypalpro_signature',false)
		);
		
		$post_string = "";
		foreach( $post_values as $key => $value ){ $post_string .= "$key=" . urlencode( $value ) . "&"; }
		$post_string = rtrim( $post_string, "& " );
		$post_string .= "&TOKEN=".$token;

		$post_response = $this->callService($post_string);		

		$response = $this->deformatNVP($post_response);
		
		$response['ACK'] = strtoupper($response['ACK']);
		if($response['ACK'] == 'SUCCESS' || $response['ACK'] == 'SUCCESSWITHWARNING'){
			return $response['CUSTOM'];
		} 
		else {
			return false;
		}
	}

	public function deformatNVP($nvpstr)
	{
		$intial=0;
		$nvpArray = array();
		while(strlen($nvpstr)){
			$keypos= strpos($nvpstr,'=');
			$valuepos = strpos($nvpstr,'&') ? strpos($nvpstr,'&'): strlen($nvpstr);
			$keyval=substr($nvpstr,$intial,$keypos);
			$valval=substr($nvpstr,$keypos+1,$valuepos-$keypos-1);
			$nvpArray[urldecode($keyval)] =urldecode( $valval);
			$nvpstr=substr($nvpstr,$valuepos+1,strlen($nvpstr));
		 }
		return $nvpArray;
	}

    public function htmlToRender()
    {
        return $this->__("Paypal website standard payment");

    }

    public function paymentStatus()
    {
        return Component_Appstore_Helpers_Data::STATUS_PAID;
    }
}